package com.sedu.manage.controller;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;
import javax.servlet.http.HttpServletResponse;

import com.sedu.common.core.domain.entity.SysUser;
import com.sedu.common.utils.DateUtils;
import com.sedu.framework.web.domain.server.Sys;
import com.sedu.manage.domain.Course;
import com.sedu.manage.domain.Subject;
import com.sedu.manage.service.ICourseService;
import com.sedu.manage.service.ISubjectService;
import com.sedu.system.domain.SysPost;
import com.sedu.system.service.ISysDeptService;
import com.sedu.system.service.ISysPostService;
import com.sedu.system.service.ISysUserService;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.sedu.common.annotation.Log;
import com.sedu.common.core.controller.BaseController;
import com.sedu.common.core.domain.AjaxResult;
import com.sedu.common.enums.BusinessType;
import com.sedu.manage.domain.Attendance;
import com.sedu.manage.service.IAttendanceService;
import com.sedu.common.utils.poi.ExcelUtil;
import com.sedu.common.core.page.TableDataInfo;

/**
 * 考勤记录Controller
 *
 * @author yulinfeng
 * @date 2025-03-29
 */
@RestController
@RequestMapping("/manage/attendance")
public class AttendanceController extends BaseController {
    @Autowired
    private ISysUserService userService;

    @Autowired
    private IAttendanceService attendanceService;

    @Autowired
    private ISysDeptService deptService;

    @Autowired
    private ISysPostService postService;

    @Autowired
    private ISubjectService subjectService;

    @Autowired
    private ICourseService courseService;

    /**
     * 查询考勤记录列表
     */
    @PreAuthorize("@ss.hasPermi('manage:attendance:list')")
    @GetMapping("/list")
    public TableDataInfo list(Attendance attendance) {
        startPage();
        List<Attendance> list = attendanceService.selectAttendanceList(attendance);
        for (Attendance attendanceTemp : list) {
            attendanceTemp.setDept(deptService.selectDeptById(attendanceTemp.getDeptId()));
            attendanceTemp.setPost(postService.selectPostById(attendanceTemp.getPostId()));
            attendanceTemp.setStudentName(userService.selectUserById(attendanceTemp.getStudentId()).getNickName());
            attendanceTemp.setSubjectId(courseService.selectCourseByCourseId(attendanceTemp.getCourseId()).getSubjectId());
            attendanceTemp.setSubjectName(subjectService.selectSubjectBySubjectId(attendanceTemp.getSubjectId()).getSubjectName());
        }
        return getDataTable(list);
    }

    /**
     * 查询所有的考勤记录
     */
    @PreAuthorize("@ss.hasPermi('manage:attendance:list')")
    @GetMapping("/all")
    public AjaxResult all(Attendance attendance) {
        List<Attendance> list = attendanceService.selectAttendanceList(attendance);
        for (Attendance attendanceTemp : list) {
            SysUser user = userService.selectUserById(attendanceTemp.getStudentId());
            attendanceTemp.setDept(deptService.selectDeptById(attendanceTemp.getDeptId()));
            attendanceTemp.setPost(postService.selectPostById(attendanceTemp.getPostId()));
            attendanceTemp.setStudentName(user.getUserName());
            attendanceTemp.setStudentNick(user.getNickName());
            attendanceTemp.setSubjectId(courseService.selectCourseByCourseId(attendanceTemp.getCourseId()).getSubjectId());
            attendanceTemp.setSubjectName(subjectService.selectSubjectBySubjectId(attendanceTemp.getSubjectId()).getSubjectName());
            attendanceTemp.setCourse(courseService.selectCourseByCourseId(attendanceTemp.getCourseId()));
            attendanceTemp.getCourse().setTeacher(userService.selectUserById(attendanceTemp.getCourse().getTeacherId()));
            attendanceTemp.getCourse().setDept(attendanceTemp.getDept());
            attendanceTemp.getCourse().setPost(attendanceTemp.getPost());
            attendanceTemp.getCourse().setSubject(subjectService.selectSubjectBySubjectId(attendanceTemp.getSubjectId()));
            attendanceTemp.getCourse().setCourseName();
        }
        return success(list);
    }

    /**
     * 查询近days天的考勤率
     */
    @PreAuthorize("@ss.hasPermi('manage:attendance:list')")
    @GetMapping("/days/attendanceRate")
    public AjaxResult daysAttendanceRate(Attendance attendance, Integer days) {
        // 得到近days天的日期列表格式为YYYY-MM-DD
        List<String> dates = new ArrayList<>();
        LocalDate today = LocalDate.now();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");

        for (int i = days - 1; i >= 0; i--) {
            LocalDate date = today.minusDays(i);
            dates.add(date.format(formatter));
        }

        // 使用attendanceService.selectAttendanceList循环查询出近days天的考勤记录
        List<Integer> dataDaysAttendanceRate = new ArrayList<>();
        for (String date : dates) {
            attendance.setAttendanceDate(DateUtils.parseDate(date));
            // 重置Status
            attendance.setStatus(null);
            int total = attendanceService.selectAttendanceList(attendance).size();
            attendance.setStatus(0L);
            int attend = attendanceService.selectAttendanceList(attendance).size();
            // 计算出考勤率，不保留小数
            int rate = (int) (((double) attend / total) * 100);
            dataDaysAttendanceRate.add(rate);
        }
        // 将日期列表格式都转化为MM-dd
        dates.replaceAll(s -> s.substring(5));

        // 创建一个字典
        Map<String, Object> result = new HashMap<>();
        result.put("dateList", dates);
        result.put("ratesList", dataDaysAttendanceRate);

        return success(result);
    }

    /**
     * 查询近days天的各班级和科目考勤率
     */
    @PreAuthorize("@ss.hasPermi('manage:attendance:list')")
    @PostMapping("/days/type/attendanceRate")
    public AjaxResult daysClassAttendanceRate(Attendance attendance, String type, Integer days) {
        // type为class表示按班级查询，为subject表示按科目查询，如果type不为class或者subject则返回错误
        if (!type.equals("class") && !type.equals("subject")) {
            return error("type错误");
        }
        List<Long> listTypeId = new ArrayList<>();
        if (type.equals("class")) {
            // 得到班级列表
            List<SysPost> listType = postService.selectPostAll();
            // 得到listType的id列表
            for (SysPost post : listType) {
                listTypeId.add(post.getPostId());
            }
        }
        if (type.equals("subject")) {
            // 得到科目列表
            List<Subject> listType = subjectService.selectSubjectList(new Subject());
            // 得到listType的id列表
            for (Subject subject : listType) {
                listTypeId.add(subject.getSubjectId());
            }
        }

        // 得到近days天的日期列表格式为YYYY-MM-DD
        List<String> dates = new ArrayList<>();
        LocalDate today = LocalDate.now();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");

        for (int i = days - 1; i >= 0; i--) {
            LocalDate date = today.minusDays(i);
            dates.add(date.format(formatter));
        }

        // 新建字典
        Map<Long, List<Integer>> listTypeData = new HashMap<>();
        // 通过循环将listType的id列表转化为listTypeData的建，值对应一个列表[0,0]分别表示总数和已出勤人数
        for (Long id : listTypeId) {
            listTypeData.put(id, new ArrayList<>(Arrays.asList(0, 0)));
        }
        // 创建一个List<Attendance>
        List<Attendance> listAttendance = new ArrayList<>();
        for (String date : dates) {
            // 将每次循环得到的列表添加到listAttendance
            attendance.setAttendanceDate(DateUtils.parseDate(date));
            List<Attendance> dayList = attendanceService.selectAttendanceList(attendance);
            // 如果Type为subject则将dayList中每个记录的course对象通过该记录的CourseId使用selectCourseByCourseId查询并赋值
            if (type.equals("subject")) {
                for (Attendance attendance1 : dayList) {
                    attendance1.setCourse(courseService.selectCourseByCourseId(attendance1.getCourseId()));
                }
            }
            listAttendance.addAll(dayList);
        }

        for (Long id : listTypeId) {
            // 如果type为class则将listAttendance中postId等于id的Attendance的总数赋给listTypeData的对应id的值的列表的0序列位置，将listAttendance中postId等于id且status为0的Attendance的总数赋给listTypeData的对应id的值的列表的1序列位置
            if (type.equals("class")) {
                listTypeData.get(id).set(0, (int) listAttendance.stream().filter(attendance1 -> attendance1.getPostId().equals(id)).count());
                listTypeData.get(id).set(1, (int) listAttendance.stream().filter(attendance1 -> attendance1.getPostId().equals(id) && attendance1.getStatus().equals(0L)).count());
            }
            if (type.equals("subject")) {
                listTypeData.get(id).set(0, (int) listAttendance.stream().filter(attendance1 -> attendance1.getCourse().getSubjectId().equals(id)).count());
                listTypeData.get(id).set(1, (int) listAttendance.stream().filter(attendance1 -> attendance1.getCourse().getSubjectId().equals(id) && attendance1.getStatus().equals(0L)).count());
            }
        }
        // 新建字典，统计考勤率。并将其按照id顺序组成一个列表，同时将id根据类型转化为对应的名称
        Map<String, Object> result = new HashMap<>();
        // 遍历listTypeId，将listTypeId的id转化为对应的名称，并将其添加到result的nameList中
        List<String> nameList = new ArrayList<>();
        for (Long id : listTypeId) {
            if (type.equals("class")) {
                nameList.add(postService.selectPostById(id).getPostName());
            }
            if (type.equals("subject")) {
                nameList.add(subjectService.selectSubjectBySubjectId(id).getSubjectName());
            }
        }
        result.put("nameList", nameList);
        // 遍历listTypeId，按照id顺序求得rate，并将其添加到result的rateList中
        List<Integer> rateList = new ArrayList<>();
        for (Long id : listTypeId) {
            // 计算出考勤率，不保留小数
            int rate = (int) (((double) listTypeData.get(id).get(1) / listTypeData.get(id).get(0)) * 100);
            rateList.add(rate);
        }
        result.put("rateList", rateList);

        return success(result);
    }

    /**
     * 查看某条件下的近days天考勤数据统计
     */
    @PreAuthorize("@ss.hasPermi('manage:attendance:list')")
    @PostMapping("/days/condition/statistics")
    public AjaxResult daysStudentAttendanceRate(Attendance attendance, Integer days) {
        // 得到近days天的日期列表格式为YYYY-MM-DD
        List<String> dates = new ArrayList<>();
        LocalDate today = LocalDate.now();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        for (int i = days - 1; i >= 0; i--) {
            LocalDate date = today.minusDays(i);
            dates.add(date.format(formatter));
        }

        // 创建一个List<Attendance>
        List<Attendance> listAttendance = new ArrayList<>();
        for (String date : dates) {
            // 将每次循环得到的列表添加到listAttendance
            attendance.setAttendanceDate(DateUtils.parseDate(date));
            // 如果attendance.subjectId不为null,则创建一个Course用来查询出对应的课程
            if (attendance.getSubjectId() != null) {
                Course course = new Course();
                course.setSubjectId(attendance.getSubjectId());
                SysUser user = userService.selectUserById(attendance.getStudentId());
                course.setDeptId(user.getDeptId());
                course.setPostId(user.getPostId());
                // 查询得到Course列表，使用selectCourseList
                List<Course> courses = courseService.selectCourseList(course);
                // 通过循环得到该课程的courseId
                for (Course courseTemp : courses) {
                    attendance.setCourseId(courseTemp.getCourseId());
                    List<Attendance> dayList = attendanceService.selectAttendanceList(attendance);
                    listAttendance.addAll(dayList);
                }
                continue;
            }
            List<Attendance> dayList = attendanceService.selectAttendanceList(attendance);
            listAttendance.addAll(dayList);
        }

        int total = listAttendance.size();
        // 查看该条件下到课次数
        int normal = (int) listAttendance.stream().filter(attendance1 -> attendance1.getStatus().equals(0L)).count();
        // 查看该条件下迟到次数，对应状态为1
        int late = (int) listAttendance.stream().filter(attendance1 -> attendance1.getStatus().equals(1L)).count();
        // 查看该条件下请假次数，对应状态为2
        int leave = (int) listAttendance.stream().filter(attendance1 -> attendance1.getStatus().equals(2L)).count();
        // 查看该条件下旷课次数，对应状态为3
        int absent = (int) listAttendance.stream().filter(attendance1 -> attendance1.getStatus().equals(3L)).count();
        // 考勤率，不保留小数
        int rate = (int) (((double) normal / total) * 100);


        // 创建结果字典
        Map<String, Integer> result = new HashMap<>();
        result.put("total", total);
        result.put("normal", normal);
        result.put("late", late);
        result.put("leave", leave);
        result.put("absent", absent);
        result.put("rate", rate);

        return success(result);

    }


    /**
     * 导出考勤记录列表
     */
    @PreAuthorize("@ss.hasPermi('manage:attendance:export')")
    @Log(title = "考勤记录", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(HttpServletResponse response, Attendance attendance) {
        List<Attendance> list = attendanceService.selectAttendanceList(attendance);
        ExcelUtil<Attendance> util = new ExcelUtil<Attendance>(Attendance.class);
        util.exportExcel(response, list, "考勤记录数据");
    }

    /**
     * 获取考勤记录详细信息
     */
    @PreAuthorize("@ss.hasPermi('manage:attendance:query')")
    @GetMapping(value = "/{attendanceId}")
    public AjaxResult getInfo(@PathVariable("attendanceId") Long attendanceId) {
        return success(attendanceService.selectAttendanceByAttendanceId(attendanceId));
    }

    /**
     * 新增考勤记录
     */
    @PreAuthorize("@ss.hasPermi('manage:attendance:add')")
    @Log(title = "考勤记录", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@RequestBody Attendance attendance) {
        // 新建一个校验Attendance对象，作用为防止重复添加
        Attendance attendanceCheck = new Attendance();
        attendanceCheck.setCourseId(attendance.getCourseId());
        attendanceCheck.setStudentId(attendance.getStudentId());
        attendanceCheck.setAttendanceDate(DateUtils.parseDate(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD, attendance.getAttendanceDate()) + " 00:00"));
        if (!attendanceService.selectAttendanceList(attendanceCheck).isEmpty()) {
            return error("该学生在该课程该日期的考勤记录已存在");
        }
        return toAjax(attendanceService.insertAttendance(attendance));
    }

    /**
     * 修改考勤记录
     */
    @PreAuthorize("@ss.hasPermi('manage:attendance:edit')")
    @Log(title = "考勤记录", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@RequestBody Attendance attendance) {
        return toAjax(attendanceService.updateAttendance(attendance));
    }

    /**
     * 删除考勤记录
     */
    @PreAuthorize("@ss.hasPermi('manage:attendance:remove')")
    @Log(title = "考勤记录", businessType = BusinessType.DELETE)
    @DeleteMapping("/{attendanceIds}")
    public AjaxResult remove(@PathVariable Long[] attendanceIds) {
        return toAjax(attendanceService.deleteAttendanceByAttendanceIds(attendanceIds));
    }
}
